/**
*
*/
package kgame5.kmath {
	import kgame5.k3d.core.math.Vector3D;
	import kgame5.kutil.*;

	public class MathDG{
	public static const 
		RTD:Number=180/3.1415926,
		DTR:Number=Math.PI/180;//
		
	//原来颜色的0~1的颜色,这个是3d里用的，其他地方也在用
	public static function ScaleColor(srcColor:int,colorScale:Number):int{
		var colorR:Number=MathDG.getR(srcColor);
		var colorG:Number=MathDG.getG(srcColor);
		var colorB:Number=MathDG.getB(srcColor);
		
		if(colorScale<0){
			colorScale=0;
		}else if(colorScale>1){
			colorScale=1;
		}
						
						
		colorR*=colorScale;
		colorG*=colorScale;
		colorB*=colorScale;
						
		var aimColor:int=MathDG.combineRGB(colorR,colorG,colorB);
		return aimColor;
	}
	//弹簧震荡的效果
	public static function Damp(current:Number,aim:Number,K:Number):Number{
		//ObjPos=targetPos-deceleration*(ObjPos-targetPos)
		//你尝试让ObjPos是任意的一个数,然后让deceleration取0~1(不包括0,1),然后targetPos取一个跟ObjPos相差比较大的数,不断地代入上式算一下,你会发现ObjPos会在targetPos两侧振动,并且当前一次大于targetPos时候,这一次将小于targetPos,而且无限接近于targetPos,于是就达到弹性振动的目的了.
		current=aim-K*(current-aim);
		return current;
	}
	
	//注意传入的current，target不能是null,注意int和Number在这里是很敏感的，搞不好就有动画哆嗦的问题
	public static function Spring (current : Number, target1 : Number, K : Number) : Number{
		
		if (Math.abs (current-target1)<=1){
			return target1;
		}
		//a1的正负
		var a1 : Number = 0;
		if (current > target1){
			a1 = - 1;
		} else if (current < target1){
			a1 = 1;
		}
		var result1 : Number = current + (target1 + a1 * K - current) / K;
		return Math.round(result1);
	}
	//注意传入的current，target不能是null
	public static function Spring3 (current : Number, target1 : Number, K : Number) : Number{
		
		if (Math.abs (current-target1)<=0.001){
			return target1;
		}
		
		var result1 : Number =current+ (target1 - current) / K;
		
		return result1;
	}
	//由慢到快运动到目标
	public static function Spring2 (current : Number, init:Number,target1 : Number, K : Number) : Number{
	 current += (current-init)*K;
	 if (init<target1){
			if(current>=target1){
				return target1;
			}
		}else if(init>target1){
			if(current<=target1){
				return target1;
			}
		}else{
			return target1;
		}
		return current;
	}
	
	
	//返回[min,max]
	public static function random (min : Number, max : Number) : Number
	{
		if(max<=min){
			return min;
		}
		var randomNum : Number = Math.floor (Math.random () * (max - min + 1)) + min;
		return randomNum;
	}
	//随机返回是否真
	//percent是返回true的概率
	public static function randomBoolean(percent:int=50):Boolean{
		var a:int=MathDG.random(1, 100);
		if(a<percent){
			return true;
		}
		return false;
	}
	//获得百分比
	public static function getPercentage (p : Number, tt : Number) : Number
	{
		return Math.floor (p * 100 / tt);
	}
	//把一个数限制在一个范围内，超过了则认为他无效
	public static function Clamp (src : Number, min : Number, max : Number) : Number
	{
		if (src > max)
		{
			return max;
		} else if (src < min)
		{
			return min;
		} else
		{
			return src;
		}
	}
	 /**
   * 是把返回值限制在[floor,ceiling)的区间内，有超了的就滚回
   * 用于翻页和圆的度数的使用
   *~是不安全的，注意 src不要超过ceiling-floor
   * //实践证明Confine()函数还是很好用的！
   * @param floor float
   * @param ceiling float
   * @param src float
   * @return float
   */
  public static function C2(src:Number,floor:Number, ceiling:Number):Number {
    if (src >= ceiling) {
      src -= ceiling - floor;
    } else if (src < floor) {
      src += ceiling - floor;
    }
    return src;
  }
	//把数字限制在[0,360)
	public static function C360(src:Number):Number{
		if(src>=360){
			src%=360;
		}else if(src<0){
			src%=360;
			src=360+src;
		}
		return src;
	}
	//匀速移动到一个指定位置,超过这个位置则就是这个位置Walk to aim
	public static function W (src : Number, aim : Number, speed : Number) : Number
	{
		speed=Math.abs(speed);//这个要保证speed是正的
		
		//T.p ("p:" + src);
		if (src > aim)
		{
			src -= speed;
			if (src < aim)
			{
				src = aim;
			}
		} else if (src < aim)
		{
			src += speed;
			if (src > aim)
			{
				src = aim;
			}
		}
		//T.p ("p:" + src);
		return src;
	}
	
	
//自动瞄准函数,x0,y0是源的,x1,y1是目标地方,ps=10就打不准了,因为后面的0.1的小数会被干掉
public static function AAA (x0:Number,y0:Number,x1:Number,y1:Number, ps:Number=1):Number {
	T.p("AAA:",x0,y0,x1,y1);
	// ps:是射击精度,因为有的人打不准啊persetion //me head up //ps range:1--360
	var angle:Number=0;
	var dx:Number = x1-x0;
	if(dx==0){//dy/dx的除数为0
		if (y1<y0) {
			angle = 270;
		} else if (y1>y0) {
			angle = 90;
		}
		return angle;
	}
	var dy:Number = y1-y0;
	 angle= Math.floor(Math.atan(dy/dx)*RTD/ps)*ps;
	if (x1<x0) {
		angle = 180+angle;
	} else if (x1>x0) {
		//angle = 270+angle;
	}
	return angle;
}

//自动瞄准函数,x0,y0是源的,x1,y1是目标地方,ps=10就打不准了,因为后面的0.1的小数会被干掉
//返回的是角度
public static function AAA2 (dx:Number,dy:Number, ps:Number=1):Number {
	//T.p("AAA:",dx,dy);
	// ps:是射击精度,因为有的人打不准啊persetion //me head up //ps range:1--360
	//var dx:Number = x1-x0;
	//var dy:Number = y1-y0;
	var angle:Number=0;
	if(dx==0){//dy/dx的除数为0
		if (dy<0) {
			angle = 270;
		} else if (dy>0) {
			angle = 90;
		}
		return angle;
	}
	
	 angle= Math.floor(Math.atan(dy/dx)*RTD/ps)*ps;
	if (dx<0) {
		angle = 180+angle;
	} else if (dx>0) {
		//angle = 270+angle;
	}
	return angle;
}
	
	
	
	/*
	////////////////////
	//angle是角度，把极坐标转换成的卡而坐标,返回一个 点
	public static function Polar(len:Number,angle:Number):Object{
		
		var p:Object=Point.polar(len,angle*Math.PI/180);
		
		var q:Object={x:Math.round(p.x),y:Math.round(p.y)};
		return q;
	}
	//得到一个从一点到另一点的指定的速度
	public static function CalcLaneSpeed(srcX,srcY,aimX,aimY,Speed):Object{
		var dx=aimX-srcX;
		var dy=aimY-srcY;
		if(dx==0&&dy==0){
			throw new Error("CalcLaneSpeed除数不能为0！！");
		}
		var c=Math.sqrt(dx*dx+dy*dy);
		
		var vx=Speed*dx/c;
		var vy=Speed*dy/c;
		
		var p={vx:vx,vy:vy};
		
		return p;
	}
	//得到一个从一点到另一点的指定的速度,c,这样避免了初始化向量，提高效率
	public static function CalcLaneSpeed3D(src:Vector3D,aim:Vector3D,c:Vector3D,speed:Number){
		//T.p("CalcLaneSpeed3D");
		//src.trace();
		//aim.trace();
		Vector3D.SSub(aim,src,c);
		c.normalize();
		//c.trace();
		c.mul(speed);
		//c.trace();
		//T.p("!!");
	}
	//*/
	public static function getDistance(x1:Number,y1:Number,z1:Number,x2:Number,y2:Number,z2:Number):Number{
		var dx:Number=x2-x1;
		var dy:Number=y2-y1;
		var dz:Number=z2-z1;
		
		return Math.sqrt(dx*dx+dy*dy+dz*dz);
	}
	public static function getR(rgb:int):int{
		return (rgb&0xff0000)>>16;
	}
	public static function getG(rgb:int):int{
		return (rgb&0x00ff00)>>8;
	}
	public static function getB(rgb:int):int{
		return rgb&0x0000ff;
	}
	public static function combineRGB(R:int,G:int,B:int):int{
		R=MathDG.C2(R,0,255);
		G=MathDG.C2(G,0,255);
		B=MathDG.C2(B,0,255);
		return R<<16|G<<8|B;
	}
	/*
	//计算两个点的朝向
	public static function CalcDir (p_x:Number, p_z:Number, aimx:Number, aimz:Number):Number {
		var _dir = Sprite3D.DIR_S;
		var xdist = Math.abs (p_x - aimx);
		var zdist = Math.abs (p_z - aimz);
		if (aimx > p_x) {
			if (aimz > p_z) {
				if (zdist > xdist) {
					_dir =Sprite3D.DIR_N;
				} else {
					_dir =Sprite3D.DIR_E;
				}
			} else if (aimz <= p_z) {
				if (zdist > xdist) {
					_dir =Sprite3D.DIR_S;
				} else {
					_dir =Sprite3D.DIR_E;
				}
			}
		} else if (aimx <= p_x) {
			if (aimz > p_z) {
				if (zdist > xdist) {
					_dir =Sprite3D.DIR_N;
				} else {
					_dir =Sprite3D.DIR_W;
				}
			} else if (aimz <= p_z) {
				if (zdist > xdist) {
					_dir =Sprite3D.DIR_S;
				} else {
					_dir =Sprite3D.DIR_W;
				}
			}
		}
		return _dir; 
	}
	
	//--
	
	//两个点之间的距离是和某个r的关系,-1是小于，0是等于，1是大于
	public static function compareR(x1:Number,y1:Number,z1:Number,x2:Number,y2:Number,z2:Number,r:Number):Number{
		var r2:Number=r*r;
		
		var dx:Number=x1-x2;
		var dy:Number=y1-y2;
		var dz:Number=z1-z2;
		
		var dx2:Number=dx*dx;
		var dy2:Number=dy*dy;
		var dz2:Number=dz*dz;
		
		if((dx2+dy2+dz2)>r2){
			return 1;
		}else if((dx2+dy2+dz2)<r2){
			return -1;
		}else{
			return 0;
		}
	}
	
	
	
	//*/
		//如果是len=4,怎返回3,4,0,1,2,5
	public static function GenRandomSequence(len:int):Array{
		len=len+1;
		var tempArray:Array = new Array();
		var array:Array = new Array();
		for (var i:int = 0; i<=len; i++) {
			tempArray.push(i);
		}
		var l:int = len;
		while (true) {
			var randNumber:Number = Math.floor(Math.random()*(len-0+1))+0;
			var temp:int = tempArray[randNumber];
			if (temp != -1) {
				array.push(temp);
			}
			tempArray[randNumber] = -1;
			if (array.length == l+1) {
				break;
			}
		}
		return array;
	}
	//如果是len=4,怎返回3,4,0,1,2
	public static function GenRandArray(len:int):Array{
		
		var tempArray:Array = new Array();
		var array:Array = new Array();
		for (var i:int = 0; i<=len; i++) {
			tempArray.push(i);
		}
		var l:int = len;
		while (true) {
			var randNumber:int = Math.floor(Math.random()*(len-0+1))+0;
			var temp:int = tempArray[randNumber];
			if (temp != -1) {
				array.push(temp);
			}
			tempArray[randNumber] = -1;
			if (array.length == l+1) {
				break;
			}
		}
		return array;
	}
	
	//旋转到上下左右4个目标方向，0，90，180，270,currentRotation,aimRotation,speed
	public static function RotateTo4Dir(cr:Number,ar:Number,sp:Number):Number{
//		if(cr>=360){
//			cr-=360;
//		}else if(cr<0){
//			cr+=360;
//		}
		if(cr==ar){
			return ar;
		}
		T.p("RotateTo4Dir",cr,ar);
		//
		switch(ar){
			case 0:
			if(cr>=0&&cr<90){
				cr-=sp;
			}else if(cr>=90&&cr<180){
				cr-=sp;
			}else if(cr>=180&&cr<270){
				cr+=sp;
			}else if(cr>=270&&cr<360){
				cr+=sp;
			}
			break;
			case 90:
			if(cr>=0&&cr<90){
				cr+=sp;
			}else if(cr>=90&&cr<180){
				cr-=sp;
			}else if(cr>=180&&cr<270){
				cr-=sp;
			}else if(cr>=270&&cr<360){
				cr+=sp;
			}
			break;
			case 180:
			if(cr>=0&&cr<90){
				cr+=sp;
			}else if(cr>=90&&cr<180){
				cr+=sp;
			}else if(cr>=180&&cr<270){
				cr-=sp;
			}else if(cr>=270&&cr<360){
				cr-=sp;
			}
			break;
			case 270:
			if(cr>=0&&cr<90){
				cr-=sp;
			}else if(cr>=90&&cr<180){
				cr+=sp;
			}else if(cr>=180&&cr<270){
				cr+=sp;
			}else if(cr>=270&&cr<360){
				cr-=sp;
			}
			break;
		}
		//trace("~",cr,ar);
		return cr;
	}
	
	
	//检查边界，把超出范围的索引做成本范围的
	public static function trimArray2Idx(a2:Array,c:int,r:int):Object{
		
		if(r<0){
			r=0;
		}else if(r>a2.length-1){
			r=a2.length-1;
		}
		
		if(c<0){
			c=0;
		}else if(c>a2[0].length-1){
			c=a2[0].length-1;
		}
		return {col:c,row:r};
	}
	
	//一个以某种速度飞行的球体的尾巴，这个是炮弹、导弹飞行的时候要计算的东西
	public static function CalcFlySphereTail(p:Vector3D,v:Vector3D,R:int):Vector3D{
		//1，取得方向
		var v_p:Vector3D= v.clone();
		v_p.normalize();
		
		v_p.reverse();
		
		//2,计算位置,得到在球面上应该冒烟的位置
		v_p.mul(R);
	
		//3,计算的到世界坐标
		v_p.add(p);
		
		return v_p;
	}
	
	//取得一个斜线上的点，y=kx+b,是一条斜线(0,maxY),(maxX,0)
	//这个用来处理随着距离儿衰减的东西
	public static function linearFunc(x:int,maxY:int,maxX:int):int{
		return -maxY/maxX*x+maxY;
	}
	
	//在A点和B点之间的一个值
	public static function linearFunc2(x1:Number,y1:Number,x2:Number,y2:Number,x:Number):Number{
		
			var y:Number;
			if(x1!=x2){
				if(y1!=y2){
					
					y=y1*(x2-x)/(x2-x1)+y2*(x-x1)/(x2-x1);
				}else{
					y=y1;
				}
			}
			
			return y;
			
		}
} //end of class
}